/// 
/// MaDAson - Toolkit for Model Driven Software Development
/// 
/// Copyright [2006] Marcus Lankenau
/// 
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///  
///     http://www.apache.org/licenses/LICENSE-2.0
///  
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// 

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Madason.TemplateCompiler
{
	public class ClassGeneratorCsharp
	{
		private string className = "Dummy";

		public string ClassName
		{
			get { return className; }
			set { className = value; }
		}
	

		public void GenerateHeader(TextWriter writer)
		{
			writer.WriteLine("using System;");
			writer.WriteLine("using System.IO;");
			writer.WriteLine("using System.Collections.Generic;");
			writer.WriteLine("");
			writer.WriteLine("public class " + ClassName);
			writer.WriteLine("{");
			writer.WriteLine("");
			writer.WriteLine("  public void Render(TextWriter writer)");
			writer.WriteLine("  {");
		}

		public void GenerateFooter(TextWriter writer)
		{
			writer.WriteLine("}");
		}



		public void Generate(TextReader template, TextWriter writer)
		{
			StringBuilder codeBlocks = new StringBuilder();
			
			Parser parser = new Parser(template);
			List<Token> tokenList = new List<Token>();
			while (true)
			{
				Token token = parser.ReadToken();
				if (token.TokenType == TokenType.EOF)
					break;
				tokenList.Add(token);
			}

			TokenlistOptimizer.OptimizeLineBreaks(tokenList);


			foreach (Token token in tokenList)
			{
				if (token.TokenType == TokenType.Scriptlet)
				{
					if (token.Content.Length == 0) continue;
					if (token.Content[0] == '@')
					{
						Regex importRegex = new Regex("Import +Namespace=\"([^\"]+)\"");
						Match match = importRegex.Match(token.Content);
						if (match.Success)
						{
							string ns = match.Groups[1].Value;
							writer.WriteLine("using " + ns + ";");
						}
					}
				}
			}

			GenerateHeader(writer);

			foreach (Token token in tokenList)
			{
				if (token.TokenType == TokenType.Text)
				{
					string[] lines = token.Content.Replace("\r", ""). Split("\n".ToCharArray());
					for (int i=0; i<lines.Length; i++)
					{
						string line = lines[i].Replace("\\", "\\\\").Replace("\"", "\\\"");
						string cmd = (i < lines.Length - 1) ? "WriteLine" : "Write";
						writer.WriteLine("    writer."+cmd+"(\"" + line + "\");");
					}
				}

				else if (token.TokenType == TokenType.Scriptlet)
				{
					if (token.Content.Length == 0) continue;
					if (token.Content[0] == '@') continue;

					if (token.Content[0] == '=')
					{
						writer.WriteLine("#line " + token.Line);
						string term = token.Content.Substring(1);
						writer.WriteLine("    writer.Write(" + term + ");");
					}
					else
					{
						writer.WriteLine("#line " + token.Line);
						writer.WriteLine(token.Content);
					}
				}

				else if (token.TokenType == TokenType.CodeBlock)
				{
					codeBlocks.Append("#line " + token.Line);
					codeBlocks.Append(token.Content);
				}
			}

			writer.WriteLine("  }");
			writer.WriteLine(codeBlocks.ToString());
			GenerateFooter(writer);
		}
	}
}
